#!/usr/bin/python
# -*- coding: utf8 -*-
import sys
import os
import cv
import numpy as np
import ctypes
import random
from OpenGL.GL import *
from OpenGL.arrays import vbo
import OpenGL
import Image
from Score import Score
from threading import Thread
from AI import AI


class BattleArena:
	VERTEX_BUFFER = None

        VERTICES = []
	TEXTURES = [
		0.0,0.0,
		1.0,0.0,
		1.0,1.0,
		0.0,1.0
	]
	

	VERTEX_OFFSET = None
	TEXTURES_OFFSET = None
	
	PLAYER_1 = None
	PLAYER_2 = None
	
	WEAPON_SIZE = None
	WEAPON_DATA = None
	WHITE_SIZE = None
	WHITE_DATA = None
	
	BALL_DIRECTION_X = True
	BALL_DIRECTION_Y = True
	
	ANGLE = 0

	OLD_WEAPON_POS = 0
	AI = None
	
	def __init__(self, program):
		self.load('VERTEX_DATA')
		self.load('VERTEX_SCORE_DATA_P1')
		self.load('VERTEX_SCORE_DATA_P2')
		self.VERTEX_OFFSET = (GLfloat * len(self.VERTICES))(*self.VERTICES)
		self.TEXTURES_OFFSET = (GLfloat * len(self.TEXTURES))(*self.TEXTURES)

		self.VERTEX_BUFFER = glGenBuffers(1)
		glBindBuffer(GL_ARRAY_BUFFER, self.VERTEX_BUFFER)
		glBufferData(GL_ARRAY_BUFFER, 
		(len(self.VERTEX_OFFSET) * 4) + (len(self.TEXTURES_OFFSET) * 4),
		np.array(self.VERTICES,dtype='f'), GL_STATIC_DRAW)
		
		glBufferSubData(GL_ARRAY_BUFFER,
		(len(self.VERTEX_OFFSET) * 4),
		(len(self.TEXTURES_OFFSET) * 4),
		np.array(self.TEXTURES,dtype='f'))
		
		vTexCoord = glGetAttribLocation( program, "vTexCoord" )
		glEnableVertexAttribArray( vTexCoord )
		glVertexAttribPointer( vTexCoord, 2, GL_FLOAT, False, 0, ctypes.c_void_p((len(self.VERTEX_OFFSET) * 4)))
		
		img = Image.open('texture.png')
		self.WHITE_SIZE = img.size
		self.WHITE_DATA = np.array(list(img.getdata()), np.uint8)
		
		img2 = Image.open('texture2.png')
		self.WEAPON_SIZE = img2.size
		self.WEAPON_DATA = np.array(list(img2.getdata()), np.uint8)
		self.AI = AI('EASY')
	
	def load(self, FILENAME):
		try:
			file = open(FILENAME)
			data = file.readlines()
			for lines in data:
				if '#' not in lines:
					lines = lines.strip('\t\n\r').replace(' ','').split(',')
					lines = map(float, lines)
					for element in lines:
							self.VERTICES.append(element)
		except ValueError:
			print 'Vertex Data has been modified'
			file.close()
			sys.exit(0)
		
		file.close()
		
	def display(self,modelview, score):
		def translation(matrix, x, y, z):
			new = np.identity((4),dtype='f')
			new[0][3] = x
			new[1][3] = y
			new[2][3] = z
			return matrix * new

		glBindBuffer(GL_ARRAY_BUFFER, self.VERTEX_BUFFER)
		glEnableVertexAttribArray(0)
		glVertexAttribPointer(0, 3, GL_FLOAT, False, 0, None)

		if self.PLAYER_1 != None:
			cv.Flip(self.PLAYER_1, None, 0)
			cv.Flip(self.PLAYER_1, None, 1)
			
			cv.CvtColor(self.PLAYER_1, self.PLAYER_1, cv.CV_BGR2RGB)
			PLAYER_1_arr = self.PLAYER_1.tostring()
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
			glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST)
			glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 640, 480, 0, GL_RGB, GL_UNSIGNED_BYTE, self.PLAYER_1.tostring())

		# Player 1 canvas
		glDrawArrays(GL_QUADS,0,4)
		
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, self.WHITE_SIZE[0], self.WHITE_SIZE[1], 0, GL_RGB, GL_UNSIGNED_BYTE, self.WHITE_DATA)

		# Seperator
		offset = 0.10
		modelViewStack = []
		while 1:
			modelViewStack.append(np.ones((4,4),dtype='f'))
			
			modelViewStack[-1] = translation(modelViewStack[-1],0.0,-offset,0.0)
			glDrawArrays(GL_QUADS,4,4)
			glUniformMatrix4fv( modelview, 1, GL_TRUE, np.array(modelViewStack[-1],dtype='f' ))

			modelViewStack.pop()
			offset = offset + 0.10
			if offset > 2.0:
				break
		
		# Ball
		glDrawArrays(GL_QUADS,8,4)

		# Score
		score.drawPlayerScore()
		
		glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, self.WEAPON_SIZE[0], self.WEAPON_SIZE[1], 0, GL_RGB, GL_UNSIGNED_BYTE, self.WEAPON_DATA)

		# Player 1 Weapon
		glDrawArrays(GL_QUADS,16,4)
		# Player 2 Weapon
		glDrawArrays(GL_QUADS,20,4)
	
	frame = 0
	def idle(self, img, weapon, score, modelview): #, PLAYER_2):
		def sound():
			randomSound = random.randint(0,30)
			if 'linux' in sys.platform:
				os.system('aplay -q sounds/' + str(randomSound) + '.wav')
				
			if 'win' in sys.platform:
				pass

		def StartDirection():
			randomDirection = random.randint(0,1)
			if randomDirection == 0:
				return True
			else:
				return False
				
		self.PLAYER_1 = img

		SPEED_X = 0.04
		SPEED_Y = self.ANGLE
		thread = Thread(target = sound)
		thread.daemon = True
		self.AI.track(self.VERTICES, self.frame, self.ANGLE)
		
		self.frame += 1
		if self.frame == 20:
			self.frame = 0
		
		if self.VERTICES[24] >= 1.0:	
			self.resetBall()
			self.ANGLE = random.uniform(0.005, 0.05) 
			score.addScore(True)
			self.BALL_DIRECTION_X = True # Change to true for correct functionality
			self.BALL_DIRECTION_Y = StartDirection()

		if self.VERTICES[30] <= -1.0:
			self.resetBall()
			self.ANGLE = random.uniform(0.005, 0.05) 
			score.addScore(False)
			self.BALL_DIRECTION_X = False # Change to false for correct functionality
			self.BALL_DIRECTION_Y = StartDirection()


		if self.VERTICES[31] >= 2.90:
				thread.start()
				self.BALL_DIRECTION_Y = False
			
		if self.VERTICES[25] <= 0.90:
				thread.start()
				self.BALL_DIRECTION_Y = True
		
		
		if self.VERTICES[24] <= self.VERTICES[51] and \
			self.VERTICES[25] <= self.VERTICES[55] and \
			self.VERTICES[34] >= self.VERTICES[52]:

			self.BALL_DIRECTION_X = True
			ballmid = self.VERTICES[31] - (self.VERTICES[31] - self.VERTICES[25])/2 
			paddlemid = self.VERTICES[55] - (self.VERTICES[55] - self.VERTICES[52])/2

			if abs(ballmid - paddlemid) > 0.05:
				if paddlemid > ballmid:
					self.ANGLE = random.uniform(0.005, 0.02) 
				if paddlemid < ballmid:
					self.ANGLE = random.uniform(0.04, 0.06)

			self.AI.defense()
			thread.start()
				
		if self.VERTICES[27] >= self.VERTICES[63] and \
			self.VERTICES[25] <= self.VERTICES[67] and \
			self.VERTICES[34] >= self.VERTICES[64]:
			self.BALL_DIRECTION_X = False

			ballmid = self.VERTICES[31] - (self.VERTICES[31] - self.VERTICES[25])/2 
			paddlemid = self.VERTICES[55] - (self.VERTICES[55] - self.VERTICES[52])/2

			if abs(ballmid - paddlemid) > 0.05:
				if paddlemid > ballmid:
					self.ANGLE = random.uniform(0.005, 0.02) 
				if paddlemid < ballmid:
					self.ANGLE = random.uniform(0.04, 0.06)
	
			thread.start()

		if self.BALL_DIRECTION_X:
			self.VERTICES[24] += SPEED_X
			self.VERTICES[27] += SPEED_X
			self.VERTICES[30] += SPEED_X
			self.VERTICES[33] += SPEED_X
		else:
			self.VERTICES[24] -= SPEED_X
			self.VERTICES[27] -= SPEED_X
			self.VERTICES[30] -= SPEED_X
			self.VERTICES[33] -= SPEED_X
			
		if self.BALL_DIRECTION_Y:
			self.VERTICES[25] += SPEED_Y
			self.VERTICES[28] += SPEED_Y
			self.VERTICES[31] += SPEED_Y
			self.VERTICES[34] += SPEED_Y
		else:
			self.VERTICES[25] -= SPEED_Y
			self.VERTICES[28] -= SPEED_Y
			self.VERTICES[31] -= SPEED_Y
			self.VERTICES[34] -= SPEED_Y
	
		if weapon != self.OLD_WEAPON_POS:
			self.OLD_WEAPON_POS = weapon

			if weapon != 0:
				loc = 2.9 - float(weapon)/100
				self.VERTICES[49] = loc - 0.345
				self.VERTICES[52] = loc - 0.345
				self.VERTICES[55] = loc
				self.VERTICES[58] = loc

		

		glBufferSubData(GL_ARRAY_BUFFER,0,
		(len(self.VERTEX_OFFSET) * 4),
		np.array(self.VERTICES,dtype='f'))		
				
		glDrawArrays(GL_QUADS,8,4)
		glDrawArrays(GL_QUADS,16,4)
	
	
	def resetBall(self):
		self.VERTICES[24] = -0.015
		self.VERTICES[25] = 1.9-0.045
		self.VERTICES[26] = 0.0

		self.VERTICES[27] = 0.015
		self.VERTICES[28] = 1.9-0.045
		self.VERTICES[29] = 0.0

		self.VERTICES[30] = 0.015
		self.VERTICES[31] = 1.9
		self.VERTICES[32] = 0.0

		self.VERTICES[33] = -0.015
		self.VERTICES[34] = 1.9
		self.VERTICES[35] = 0.0

	def moveP1(self, boole):
		if boole:
			self.VERTICES[49] += 0.2
			self.VERTICES[52] += 0.2
			self.VERTICES[55] += 0.2
			self.VERTICES[58] += 0.2

		else:
			self.VERTICES[49] -= 0.2
			self.VERTICES[52] -= 0.2
			self.VERTICES[55] -= 0.2
			self.VERTICES[58] -= 0.2

	

